#include "bspfile.hpp"

namespace BSPFile
{
	static UInt32 SwapUInt32(UInt32 i)
	{
		union
		{
			UInt8 bytes[4];
			UInt32 i;
		} u;

		u.i = i;
		return u.bytes[0] | (u.bytes[1] << 8) | (u.bytes[2] << 16) | (u.bytes[3] << 24);
	}

	static void SwapInPlace(Float32 &v)
	{
		union
		{
			UInt32 i;
			Float32 f;
		} u;
		u.f = v;
		u.i = SwapUInt32(u.i);
		v = u.f;
	}

	static void SwapInPlace(UInt32 &v)
	{
		v = SwapUInt32(v);
	}

	static void SwapInPlace(Int32 &v)
	{
		union
		{
			UInt32 ui;
			Int32 i;
		} u;
		u.i = v;
		u.ui = SwapUInt32(u.ui);
		v = u.i;
	}

	template<LargeInt _Tdim>
	inline void SwapInPlace(Vec<Float32,_Tdim> &v)
	{
		for(LargeInt i=0;i<_Tdim;i++)
			SwapInPlace(v[i]);
	}

	void BSPTextureInfo_D::Swap()
	{
		SwapInPlace(this->surfaceFlags);
		SwapInPlace(this->contentFlags);
	}

	void BSPPlane_D::Swap()
	{
		SwapInPlace(this->normal);
		SwapInPlace(this->dist);
	};

	void BSPNode_D::Swap()
	{
		SwapInPlace(this->planeIndex);
		SwapInPlace(this->children[0]);
		SwapInPlace(this->children[1]);
		for(int i=0;i<3;i++)
		{
			SwapInPlace(this->mins[i]);
			SwapInPlace(this->maxs[i]);
		}
	}

	void BSPLeaf_D::Swap()
	{
		SwapInPlace(this->cluster);
		SwapInPlace(this->area);
		for(int i=0;i<3;i++)
		{
			SwapInPlace(this->mins[i]);
			SwapInPlace(this->maxs[i]);
		}
		SwapInPlace(this->leafFace);
		SwapInPlace(this->numLeafFaces);
		SwapInPlace(this->leafBrush);
		SwapInPlace(this->numLeafBrushes);
	}

	void BSPModel_D::Swap()
	{
		SwapInPlace(this->mins);
		SwapInPlace(this->maxs);
		SwapInPlace(this->gridSize);
		SwapInPlace(this->gridOrigin);
		for(int i=0;i<3;i++)
			SwapInPlace(this->gridBounds[i]);
		SwapInPlace(this->gridScalar);
		SwapInPlace(this->face);
		SwapInPlace(this->numFaces);
		SwapInPlace(this->brush);
		SwapInPlace(this->numBrushes);
	}

	void BSPBrushSide_D::Swap()
	{
		SwapInPlace(this->plane);
		SwapInPlace(this->texture);
	}


	void BSPEffect_D::Swap()
	{
		SwapInPlace(this->brushSide);
		SwapInPlace(this->sceneVolume);
		SwapInPlace(this->brush);
		SwapInPlace(this->fogColor);
		SwapInPlace(this->fogDensityScalar);
	}

	void BSPFace_D::Swap()
	{
		SwapInPlace(this->texture);
		SwapInPlace(this->smoothingGroup);
		SwapInPlace(this->effect);
		SwapInPlace(this->faceType);
		SwapInPlace(this->vertex);
		SwapInPlace(this->numVertexes);
		SwapInPlace(this->meshVert);
		SwapInPlace(this->numMeshVerts);
		SwapInPlace(this->lightMap);

		SwapInPlace(this->lightMapCoords[0]);
		SwapInPlace(this->lightMapCoords[1]);
		SwapInPlace(this->lightMapSize[0]);
		SwapInPlace(this->lightMapSize[1]);

		SwapInPlace(this->lightMapOrigin);

		SwapInPlace(this->lightMapMatrix[0]);
		SwapInPlace(this->lightMapMatrix[1]);
		SwapInPlace(this->lightMapMatrix[2]);

		SwapInPlace(this->patchDimensions[0]);
		SwapInPlace(this->patchDimensions[1]);

		SwapInPlace(this->linkedScenes[0]);
		SwapInPlace(this->linkedScenes[1]);
	}

	void BSPLightVolumeValues_D::Swap()
	{
		for(int i=0;i<9;i++)
			for(int j=0;j<256;j++)
				for(int k=0;k<3;k++)
					SwapInPlace(this->coefs[i][j][k]);
	}

	void BSPLightVolume_D::Swap()
	{
	}

	void BSPScene_D::Swap()
	{
		SwapInPlace(this->target);
		SwapInPlace(this->visibleInVolume);
		SwapInPlace(this->drawInVolume);
		SwapInPlace(this->planeNum);
		SwapInPlace(this->sceneFlags);
	}

	void BSPRTLight_D::Swap()
	{
		SwapInPlace(this->mode);
		SwapInPlace(this->origin);
		SwapInPlace(this->color);

		for(int i=0;i<9;i++)
			SwapInPlace(this->parameters[i]);
	}

	void BSPVertex_D::Swap()
	{
		unsigned int i;

		SwapInPlace(this->position);
		SwapInPlace(this->normal);

		SwapInPlace(this->texCoords);
		SwapInPlace(this->lightMapTexCoords);

		SwapInPlace(this->svec);
		SwapInPlace(this->tvec);
	}

	void BSPBrush_D::Swap()
	{
		SwapInPlace(this->brushside);
		SwapInPlace(this->numBrushSides);
		SwapInPlace(this->texture);
	}

	void BSPIndex_D::Swap()
	{
		SwapInPlace(this->idx);
	}

	void BSPAreaPortal_D::Swap()
	{
		SwapInPlace(this->firstWinding);
		SwapInPlace(this->leaf);
		SwapInPlace(this->numWindings);
	}

	void BSPAreaPortalWinding_D::Swap()
	{
		SwapInPlace(this->firstPoint);
		SwapInPlace(this->numPoints);
		SwapInPlace(this->outsideArea);
		SwapInPlace(this->plane);
	}

	void BSPAreaPortalPoint_D::Swap()
	{
		SwapInPlace(this->point);
	}
}
